/*
 *  RapidMiner
 *
 *  Copyright (C) 2001-2007 by Rapid-I and the contributors
 *
 *  Complete list of developers available at our web site:
 *
 *       http://rapid-i.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package rs.fon.rapidminer.validation;

import java.util.List;

import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.IOContainer;
import com.rapidminer.operator.IOObject;
import com.rapidminer.operator.Model;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.OperatorChain;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.condition.CombinedInnerOperatorCondition;
import com.rapidminer.operator.condition.InnerOperatorCondition;
import com.rapidminer.operator.condition.SpecificInnerOperatorCondition;

import com.rapidminer.operator.performance.PerformanceVector;

import com.rapidminer.parameter.ParameterType;

import com.rapidminer.tools.math.SignificanceTestResult;


/**
 * A ValidationChain for the 5x2cv F-test
 * 
 * @author Milos Jovanovic
 * @version $Id: MyValidationChain.java,v 0.2 2009/03/13$
 */

public abstract class MyValidationChain extends OperatorChain {
	
	private IOContainer learnResult;

	public MyValidationChain(OperatorDescription description) {
		super(description);
	}
	
	public abstract SignificanceTestResult compareClassifiers(ExampleSet inputSet) throws OperatorException;

	
	public List<ParameterType> getParameterTypes() {
		List<ParameterType> types = super.getParameterTypes();
		return types;
	}

	/** Returns the maximum number of innner operators. */
	public int getMaxNumberOfInnerOperators() {
		return 3;
	}

	/** Returns the minimum number of innner operators. */
	public int getMinNumberOfInnerOperators() {
		return 3;
	}

	/** Returns the the classes this operator provides as input. */
	public Class[] getInputClasses() {
		return new Class[] { ExampleSet.class };
	}

	/** Returns the the classes this operator expects as output. */
	public Class[] getOutputClasses() {
		return new Class[] { SignificanceTestResult.class };
	}

	public InnerOperatorCondition getInnerOperatorCondition() {
		CombinedInnerOperatorCondition condition = new CombinedInnerOperatorCondition();
		condition.addCondition(new SpecificInnerOperatorCondition("Training1", 0, new Class[] { ExampleSet.class }, new Class[] { Model.class }));
		condition.addCondition(new SpecificInnerOperatorCondition("Training2", 1, new Class[] { ExampleSet.class }, new Class[] { Model.class }));
		condition.addCondition(new SpecificInnerOperatorCondition("Testing", 2, new Class[] { ExampleSet.class, Model.class }, new Class[] { PerformanceVector.class }));
		return condition;
	}

	protected Operator getLearner(int operatorNumber) {
		return getOperator(operatorNumber-1);
	}

	protected Operator getEvaluator() {
		return getOperator(2);
	}

	protected Model learn(int learnerNumber, ExampleSet trainingSet) throws OperatorException {
		//learn model 
		IOContainer result = getLearner(learnerNumber).apply(new IOContainer(new IOObject[] { trainingSet }));
		
		//return model
		Model m = (Model)result.get(Model.class); 
		return m;
	}

	protected PerformanceVector evaluate(Model m, ExampleSet testSet) throws OperatorException {

		//prepare input for evaluation
		IOContainer evalInput = new IOContainer();
		evalInput = evalInput.append(new IOObject[] {m});
		evalInput = evalInput.append(new IOObject[] {testSet});
	
		//get results from Operator for evaluation
		IOContainer result = getEvaluator().apply(evalInput);
		
		//return result
		PerformanceVector pv = (PerformanceVector)result.get(PerformanceVector.class);
		return pv;
	}
	
	
	public IOObject[] apply() throws OperatorException {
		//get input dataset
		ExampleSet eSet = getInput(ExampleSet.class);
		
		//compare classifiers
		SignificanceTestResult comparation = compareClassifiers(eSet);
		
		//return results
		IOObject[] results = new IOObject[1];
		results[0] = comparation; 
		return results;
	}

	
	
	}
